#include <ximera/input/dinput8/inputsystem.hpp>
#include <ximera/input/dinput8/keyboard.hpp>
#include <ximera/input/dinput8/mouse.hpp>
#include <ximera/input/dinput8/main.hpp>
#include <ximera/common/utils.hpp>

#include <boost/lexical_cast.hpp>

namespace ximera { namespace input { namespace dinput8
{
    InputSystem::InputSystem(system::Application& app)
        : _msgqueue(new threading::MessageQueue()),
          _hwnd(0)
    {
        IDirectInput8* dinput = NULL;
        HRESULT hr = DirectInput8Create(DllInstance, 0x0800, IID_IDirectInput8, (LPVOID*)&dinput, NULL);
        XIMERA_CHECK(hr == DI_OK, XIMERA_THROW(InputSystemException, HResultToString(hr)));

        _dinput.reset(dinput, false);
        _hwnd = reinterpret_cast<HWND>(boost::lexical_cast<Int64>(app.settings().value(L"ximera.window.handle")));

        _keyboard.reset(new Keyboard(_hwnd, _msgqueue, _dinput));
        _mouse.reset(new Mouse(_hwnd, _msgqueue, _dinput));
    }

    InputSystem::~InputSystem()
    {
    }

    void InputSystem::update()
    {
        if (_keyboard)
            ((Keyboard*)_keyboard.get())->update();

        if (_mouse)
            ((Mouse*)_mouse.get())->update();

        if (_msgqueue)
            _msgqueue->processMessages();
    }

    SharedPtr<input::IDevice> InputSystem::device(input::DeviceType const& deviceType)
    {
        UInt32 index = static_cast<UInt32>(deviceType.value);

        if (index < _devices.size())
            return _devices[index];

        return SharedPtr<input::IDevice>();
    }

    SharedPtr<input::IKeyboard> InputSystem::keyboard()
    {
        /*UInt32 index = static_cast<UInt32>(DeviceType::Keyboard);

        if (index < _devices.size())
            return static_pointer_cast<IKeyboard>(_devices[index]);

        return SharedPtr<IKeyboard>();*/
        return _keyboard;
    }

    SharedPtr<input::IMouse> InputSystem::mouse()
    {
        /*UInt32 index = static_cast<UInt32>(DeviceType::Mouse);

        if (index < _devices.size())
            return static_pointer_cast<IMouse>(_devices[index]);

        return SharedPtr<IMouse>();*/
        return _mouse;
    }
}}}